package com.magiccompass.alipay.barcode.controller;

import java.net.URI;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import com.magiccompass.alipay.barcode.constants.AlipayPartnerConstants;
import com.magiccompass.alipay.barcode.entity.AlipayBarcodePaymentRequest;
import com.magiccompass.alipay.barcode.entity.MerchantTransaction;
import com.magiccompass.alipay.barcode.model.AlipayBarcodeAllResponseAJAXModel;
import com.magiccompass.alipay.barcode.service.AlipayBarcodeService;
import com.magiccompass.alipay.barcode.service.MerchantBusinessService;
import com.magiccompass.alipay.barcode.responsehandler.PaymentResponseHandler;
import com.magiccompass.alipay.barcode.security.model.LoginUserModel;
import com.magiccompass.alipay.barcode.util.AlipayBarcodeRequestUtil;
import com.magiccompass.alipay.barcode.util.AlipayTransactionQueryUtil;
import com.magiccompass.alipay.barcode.util.UrlUtil;
import com.magiccompass.alipay.barcode.util.UserUtil;

@Controller
@RequestMapping(value="/alipayBarcodePaymentController")
public class AlipayBarcodePaymentController {
	static Logger logger = LogManager.getLogger(AlipayBarcodePaymentController.class.getName());

	@Resource(name="alipayBarcodeService")
	private AlipayBarcodeService alipayBarcodeService;
	@Resource(name="merchantBusinessService")
	private MerchantBusinessService merchantBusinessService;
	 
	/*
	@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})
    public String alipayBarcodeScanner(Model model,HttpServletRequest request) {
		String mtId = request.getParameter("mtId");
		String totalAmt = request.getParameter("totalAmt");
		MerchantTransaction mt = null;
		
		if(mtId == null || mtId.isEmpty()){
			mt = MerchantTransactionUtil.makeBasicMerchantTransaction(mpiService.findMerchantById(1), new BigDecimal(0), mpiService);
		}else{
			mt = mpiService.findMerchantTransactionById(Integer.parseInt(mtId));
		}
		model.addAttribute("merchantTransactionId", mtId);
		model.addAttribute("totalAmt", totalAmt);
		model.addAttribute("merchantName", mt.getMerchant().getMerchantName());
        return "alipay_barcode_gateway/barcodePayment";
    }
	
	@RequestMapping(value="/barcodePaymentTest", method = {RequestMethod.GET,RequestMethod.POST})
    public String barcodePaymentTest(Model model,HttpServletRequest request) {
		String mtId = request.getParameter("mtId");
		String totalAmt = request.getParameter("totalAmt");
		MerchantTransaction mt = null;
		
		if(mtId == null || mtId.isEmpty()){
			totalAmt = "0";
			mt = MerchantTransactionUtil.makeBasicMerchantTransaction(mpiService.findMerchantById(1), new BigDecimal(totalAmt), mpiService);
		}else{
			mt = mpiService.findMerchantTransactionById(Integer.parseInt(mtId));
		}
		model.addAttribute("merchantTransactionId", mt.getId());
		model.addAttribute("totalAmt", mt.getTotalAmount());
		model.addAttribute("merchantName", mt.getMerchant().getMerchantName());
        return "alipay_barcode_gateway/barcodePaymentTest";
    }
	*/
	@RequestMapping(value="/alipayBarcodePayment", method = {RequestMethod.GET,RequestMethod.POST}, produces = "application/json; charset=UTF-8")
    public @ResponseBody String alipayBarcodePayment(Model model,HttpServletRequest request) {
		String customerALIPAYBarcode = request.getParameter("customerALIPAYBarcode");
		String merchantTransactionId = request.getParameter("merchantTransactionId");
		Integer mtId = new Integer(merchantTransactionId);
		
		MerchantTransaction mt =  merchantBusinessService.findMerchantTransactionById(mtId);
		
		AlipayBarcodePaymentRequest abpr = alipayBarcodeService.findAlipayBarcodePaymentRequestByMerchantTransactionId(mtId);
		
		AlipayBarcodeAllResponseAJAXModel returnJSON = new AlipayBarcodeAllResponseAJAXModel();
		returnJSON.setSuccess("true");
		returnJSON.setRedirect("true");
		returnJSON.setRedirectURL(request.getContextPath()+"/alipayBarcodePaymentController/result");
		
		if(customerALIPAYBarcode == null || "".equals(customerALIPAYBarcode)){ //barcode scan failed
			returnJSON.setResponseResultCode("UNEXPECTED");
			returnJSON.setResponseResultReason("Scan customer barcode error, Please contact support.");
		}else if(abpr != null){ //Merchant Transaction has has request
			returnJSON.setResponseResultCode("UNEXPECTED");
			returnJSON.setResponseResultReason("This transaction is already have payment, Please contact support.");
		}else{
			LoginUserModel currentUser = UserUtil.getCurrentLoginUser();
			AlipayBarcodePaymentRequest abpreq = AlipayBarcodeRequestUtil.alipayBarcodeRequestEntityInit(mt,customerALIPAYBarcode,currentUser.getLoginUserId());
			
			TreeMap<String,String> barcodeRequestParameter4AlipayTreeMap = AlipayBarcodeRequestUtil.makeParameterMap4Alipay(abpreq,alipayBarcodeService);
			String sign = AlipayBarcodeRequestUtil.getSign(barcodeRequestParameter4AlipayTreeMap);
			abpreq.setSign(sign);
			
			alipayBarcodeService.save(abpreq);
			
			barcodeRequestParameter4AlipayTreeMap.put("sign", abpreq.getSign());
			barcodeRequestParameter4AlipayTreeMap.put("sign_type", AlipayPartnerConstants.SIGN_TYPE);
			
			if(abpreq.getId() != null){ // success insert into DB
				try {					
					RestTemplate restTemplate = new RestTemplate();
					
					String alipayBarcodeServerURL = AlipayPartnerConstants.ALIPAY_GATEWAY;
			    	String alipayBarcodeParameter = UrlUtil.makeParameterMap2String(barcodeRequestParameter4AlipayTreeMap);
			    	String restURL = alipayBarcodeServerURL+"?"+alipayBarcodeParameter;
			    	logger.info("restURL:"+restURL);
			    	URI uri = new URI(restURL);
					//String response = restTemplate.getForObject(restURL, String.class);
			    	String response = restTemplate.getForObject(uri, String.class);
			    	//String response = PaymentResponseHandler.RESULT_PAYMENT_UNKNOWN_4_TEST;
					logger.info("response is:"+response);
					
					AlipayBarcodeAllResponseAJAXModel alipayResponse = PaymentResponseHandler.handleResponse(response, abpreq, alipayBarcodeService);
					
					String paymentAlipayResultCode = alipayResponse.getResponseResultCode();
					
					if("UNKNOW".equals(paymentAlipayResultCode)){ // unknown status, we should try to sync with alipay to get new status.
						int timeoutSeconds = 0;
						String alipayQueryStatus = "U";
						while(timeoutSeconds<=60000 && "U".equals(alipayQueryStatus)){ // in 60 seconds, try MT status is still "U"
							Thread.sleep(15000); // sleep 20 seconds, then retry
							timeoutSeconds += 15000;
							alipayQueryStatus = AlipayTransactionQueryUtil.queryTransactionStatus(mtId, merchantBusinessService, alipayBarcodeService);
						}
						if("U".equals(alipayQueryStatus)){ // still in unknown status, we should reverse it automatically.
							AlipayBarcodeReverseController abrc = new AlipayBarcodeReverseController();
							alipayResponse = abrc.paymentDirectReverse(request,merchantTransactionId,alipayBarcodeService,merchantBusinessService);
						}else{
							alipayResponse = PaymentResponseHandler.handleResultFromQueryStatus(alipayQueryStatus, abpreq, alipayBarcodeService);
						}
					}
					returnJSON.setResponseResultCode(alipayResponse.getResponseResultCode());
					returnJSON.setResponseResultReason(alipayResponse.getResponseResultReason());
				} catch (Exception e) {
					e.printStackTrace();
					returnJSON.setResponseResultCode("UNEXPECTED EXCEPTION");
					returnJSON.setResponseResultReason("Unexpected exception happened. Please contact support.");
				}
	    	}else{
	    		returnJSON.setResponseResultCode("UNEXPECTED");
				returnJSON.setResponseResultReason("Unexpected ERROR happened. Please contact support.");
	    	}
	    	/*
			returnJSON.setResponseResultCode("SUCCESS");
			returnJSON.setResponseResultReason("Please continue");
			*/
		}
		//logger.info("before returnJSON, resultCode:"+returnJSON.getResponseResultCode()+", resultReason:"+returnJSON.getResponseResultReason()+", redir:"+returnJSON.getRedirect()+","+returnJSON.getRedirectURL());
		String returnStr = returnJSON.makeJSONString();
		logger.info(returnStr);
		return returnStr;
    }
	
	@RequestMapping(value="/result", method = {RequestMethod.GET,RequestMethod.POST})
    public String result(Model model,HttpServletRequest request) {
		String resultCode = request.getParameter("resultCode");
		String resultReason = request.getParameter("resultReason");
		
		String messageType = "alert-danger";
		if("SUCCESS".equals(resultCode)){
			messageType = "alert-success";
		}
		
		String message = "Your operation result is "+resultCode+". "+resultReason;
		
		model.addAttribute("message",message);
		model.addAttribute("messageType",messageType);
		return "common/result";
    }
}